package com.zhangtai.modules.service.login;




import com.zhangtai.consts.CommonConstr;
import com.zhangtai.exception.RException;
import com.zhangtai.modules.controller.admin.JobController;
import com.zhangtai.modules.dao.EmployeeInfoDao;
import com.zhangtai.modules.dao.UserDao;
import com.zhangtai.modules.entity.employee.EmployeeInfoEntity;
import com.zhangtai.modules.entity.system.UserEntity;
import com.zhangtai.utils.CookieUtils;
import com.zhangtai.utils.DateUtils;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Configuration
@RestController
@Slf4j
public class JwtEncodeAndEncode {
    private static final String AdminCookieName="Authorization";

    @Autowired
    private RedisTemplate redisTemplate;

    //读取密钥的配置
    @Bean("keyProp")
    public KeyProperties keyProperties(){
        return new KeyProperties();
    }

    @Resource(name = "keyProp")
    private KeyProperties keyProperties;

    @Autowired
    private UserDao userDao;
    @Autowired
    private JobController jobController;
    @Autowired
    private EmployeeInfoDao employeeInfoDao;


    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();

        KeyPair keyPair = new KeyStoreKeyFactory(
                keyProperties.getKeyStore().getLocation(),                          //证书路径
                keyProperties.getKeyStore().getSecret().toCharArray())              //证书秘钥
                .getKeyPair(
                        keyProperties.getKeyStore().getAlias(),                     //证书别名
                        keyProperties.getKeyStore().getPassword().toCharArray());
        converter.setKeyPair(keyPair);

        return converter;
    }


    public String encodeUser(@RequestBody UserEntityOauth sysUserOauth) throws Exception {
        Long userId = sysUserOauth.getUserId();

        KeyPair keyPair = new KeyStoreKeyFactory(
                keyProperties.getKeyStore().getLocation(),                          //证书路径
                keyProperties.getKeyStore().getSecret().toCharArray())              //证书秘钥
                .getKeyPair(
                        keyProperties.getKeyStore().getAlias(),                     //证书别名
                        keyProperties.getKeyStore().getPassword().toCharArray());
        PrivateKey privateKey = keyPair.getPrivate();
        ArrayList<String> l1 = new ArrayList<>();
        l1.add("mabach");
        ArrayList<String> l2 = new ArrayList<>();
        l2.add("ehr");


        String uuid = UUID.randomUUID().toString().replace("-", "");
        String token = Jwts.builder()
                .claim("id",userId+"" )
                .claim("user_name", sysUserOauth.getUsername())
//                .claim("role", sysUserOauth.getRole())
                .claim("name", sysUserOauth.getName())
                .claim("usercode", sysUserOauth.getUsercode()) //管理员工号
                .claim("jobname", sysUserOauth.getJobname())
//                .claim("qwAccount", sysUserOauth.getQwAccount()) //企微推送账号
                .claim("orgname", sysUserOauth.getOrgname())
                .claim("department", sysUserOauth.getDepartment())
                .claim("orgId", sysUserOauth.getOrgId())
                .claim("depId", sysUserOauth.getDepId())
                .claim("mobile", sysUserOauth.getMobile())
                .claim("uuid", uuid) //用redis作为key,在redis保存过期信息和
//                .claim("menu", hashSet)
                .claim("aud", l1)
                .claim("scope", l2)
                .claim("client_id", "admin")
                .claim("authorities", sysUserOauth.getAuthorities())
                .setExpiration(DateUtils.addDateSeconds(new Date(), Integer.MAX_VALUE))
                .signWith(SignatureAlgorithm.RS256, privateKey)
                .compact();
//        将token封装进cookies
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        CookieUtils.setCookie(request,response,AdminCookieName,token,1000*60*60*24);

        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        stringObjectHashMap.put("flag",true);  //是否生效标志
        stringObjectHashMap.put("expire",DateUtils.addDateHours(new Date(),24)); //token过期时间
        redisTemplate.boundHashOps(uuid).put(CommonConstr.LOGIN_ITEM,stringObjectHashMap);
        redisTemplate.expire(uuid,25, TimeUnit.HOURS);

//        log.info("uuid==========>>>:{}",uuid);
//        将token存入表中
        UserEntity userEntity = new UserEntity();
        userEntity.setUserId(userId);
        userEntity.setToken(uuid);
        userDao.updateById(userEntity);



//        log.info("生成的token是：{}",token);

        return token;


    }

    /**
     * 加密员工账号
     * @param employeeInfoEntity
     * @return
     * @throws Exception
     */
    public String encodeMember(@RequestBody EmployeeInfoEntity employeeInfoEntity) throws Exception {
        Long oid = employeeInfoEntity.getOid();

        KeyPair keyPair = new KeyStoreKeyFactory(
                keyProperties.getKeyStore().getLocation(),                          //证书路径
                keyProperties.getKeyStore().getSecret().toCharArray())              //证书秘钥
                .getKeyPair(
                        keyProperties.getKeyStore().getAlias(),                     //证书别名
                        keyProperties.getKeyStore().getPassword().toCharArray());
        PrivateKey privateKey = keyPair.getPrivate();
        ArrayList<String> l1 = new ArrayList<>();
        l1.add("mabach");
        ArrayList<String> l2 = new ArrayList<>();
        l2.add("ehr");

        Long jobId = employeeInfoEntity.getJobId();
        String jobName = jobController.getJobName(jobId);
        Long orgId = employeeInfoEntity.getOrgId();
        String orgNameById = jobController.getOrgNameById(orgId);
        Long unitId = employeeInfoEntity.getUnitId();
        String unitName = jobController.getOrgNameById(unitId);
        Date hiredate = employeeInfoEntity.getHiredate();
        Integer days = DateUtils.daysBetween(hiredate, new Date());
        if (days<0){
            days=0;
        }



        String uuid = UUID.randomUUID().toString().replace("-", "");
        String token = Jwts.builder()
                .claim("id",oid+"" )
                .claim("useraccount", employeeInfoEntity.getUseraccount())
                .claim("name", employeeInfoEntity.getName())
                .claim("usercode", employeeInfoEntity.getCode()) //员工号
//                .claim("jobId", jobId)
//                .claim("jobLevelId", employeeInfoEntity.getJobLevelId())
//                .claim("jobLevel", employeeInfoEntity.getJobLevel())
//                .claim("jobLevelType", employeeInfoEntity.getJobLevelType())
//                .claim("jobname", jobName)
                .claim("mobile", employeeInfoEntity.getMobile())
                .claim("hireAge", days)
                .claim("hiredate", DateUtils.format(employeeInfoEntity.getHiredate(),DateUtils.DATE_PATTERN))
                .claim("birthday", DateUtils.format(employeeInfoEntity.getBirthday(),DateUtils.DATE_PATTERN))

//                .claim("qwAccount", sysUserOauth.getQwAccount()) //企微推送账号
//                .claim("orgname", orgNameById)
//                .claim("department", unitName)
//                .claim("orgId", orgId)
//                .claim("depId", unitId)
                .claim("gender",employeeInfoEntity.getGender())
                .claim("avatar", employeeInfoEntity.getAvatar()) //企微头像
                .claim("uuid", uuid) //用redis作为key,在redis保存过期信息和
//                .claim("menu", hashSet)
                .claim("aud", l1)
                .claim("scope", l2)
                .claim("client_id", "mabach")
                .claim("authorities", new ArrayList<>())
                .setExpiration(DateUtils.addDateSeconds(new Date(), Integer.MAX_VALUE))
                .signWith(SignatureAlgorithm.RS256, privateKey)
                .compact();
//        将token封装进cookies
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        CookieUtils.setCookie(request,response,"MemberToken",token,1000*60*30);

        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        stringObjectHashMap.put("flag",true);  //是否生效标志
        stringObjectHashMap.put("expire",DateUtils.addDateMinutes(new Date(),30)); //token过期时间
        redisTemplate.boundHashOps(uuid).put(CommonConstr.LOGIN_ITEM,stringObjectHashMap);
        redisTemplate.expire(uuid,31, TimeUnit.MINUTES);

//        log.info("uuid==========>>>:{}",uuid);
//        将token存入表中

        employeeInfoEntity.setUuid(uuid);
        employeeInfoEntity.setUpdateTime(new Date());
        employeeInfoDao.updateById(employeeInfoEntity);


//        log.info("生成的token是：{}",token);

        return token;


    }

    /**
     * 解密
     * @param token
     * @return
     */
    public  String decode(String token){
        if (StringUtils.isEmpty(token)){
            throw new RException("token为空");
        }
        String publicKey = null;

        ClassPathResource resource = new ClassPathResource("public.key");

        try {
            publicKey = IOUtils.toString(resource.getInputStream(), "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        String claims = JwtHelper.decodeAndVerify(token, new RsaVerifier(publicKey)).getClaims();
        return claims;
    }




    /**
     * 采用数据库管理令牌
     * @return
     */
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());

    }
}
